home *** CD-ROM | disk | FTP | other *** search
/ PC Media 4 / PC MEDIA CD04.iso / share / udos / srdisk13 / srdisk.asm < prev    next >
Assembly Source File  |  1992-01-17  |  52KB  |  1,515 lines

  1. ;
  2. ;       ReSizeable RAMDisk device driver for XMS memory
  3. ;
  4. ;       Copyright (c) 1992 Marko Kohtala
  5. ;
  6. ;       Some documentation and license available in accompanying file
  7. ;       SRDISK.DOC. If not, contact author by sending E-mail from
  8. ;
  9. ;               Internet, Bitnet etc. to 'Marko.Kohtala@hut.fi'
  10. ;               CompuServe to '>INTERNET:Marko.Kohtala@hut.fi'
  11. ;
  12. ;       or by calling Airline QBBS, 24H, HST, V.32, V.42, MNP,
  13. ;       +358-0-8725380, and leaving mail to me, Marko Kohtala.
  14. ;
  15. ;       In general, this is FREEWARE.
  16. ;
  17. ;       To compile with TASM: tasm /m2 srdisk.asm
  18. ;                             tlink /t srdisk.obj,srdisk.sys
  19. ;
  20. ; History:
  21. ; 1.00  Initial release
  22. ; 1.10  Added into IOCTL_msg media_change byte, that must be changed to
  23. ;       -1 by srdisk if media changed. Changed header version to SRD 1.10.
  24. ; 1.20  Fixed name of program by adding the missing 'Re' to 'Sizeable'.
  25. ;       Upgraded IOCTL_msg_s to version 1.20 by adding byte to tell usable
  26. ;       memory types.
  27. ;       Updated to work with DOS versions 2.x-5.x - not tested.
  28. ; 1.30
  29. ;       Major redesign of the reformatting system. Ioctl is no longer used.
  30. ;       New data structures of version V_FORMAT 0 (beta format).
  31. ;       Support for multiplex interrupt.
  32. ;       Support for chaining of drivers for different memory to same disk.
  33. ;       Support for DOS 4+ 32-bit sector addresses.
  34. ;       [Allow forcing drive to some drive letter (even replace DOS drives).]
  35. ;       Int 19 hooking is optional by defining HOOKINT19 to 0.
  36. ;       Added if ... endif around all memory specific code to ease
  37. ;        later adding of other memory support code.
  38. ;       Fixed parameter reading to abort on every ctrl-character other
  39. ;        than tab. DOS 5 could end line with LF if no parameters and CR if
  40. ;        there were parameters. Now even NUL can end the line.
  41.  
  42. SRD_VERSION     equ "1.30"      ; FOUR LETTER VERSION STRING
  43.  
  44. ; General capabilities in conf.c_flags
  45.  
  46. C_APPENDED      equ 1   ; Capable of having appended drivers
  47. C_MULTIPLE      equ 2   ; Capable of driving many disks
  48. C_32BITSEC      equ 4   ; Capable of handling over 32-bit sector addresses
  49. C_UNKNOWN       equ 0xF8
  50.  
  51. ; What this driver can actually do
  52. ; Currently compiled for only C_32BITSEC, since no drivers for
  53. ; any other memory available and thus C_APPENDED is useless
  54.  
  55. ;CAPABLE         equ C_APPENDED or C_32BITSEC
  56. CAPABLE         equ C_32BITSEC
  57.  
  58. ; Boolean
  59. TRUE    EQU 1
  60. FALSE   EQU 0
  61.  
  62.  
  63. ; What memory this driver supports
  64.  
  65. XMS_MEMORY      equ     TRUE
  66.  
  67. ; Some important internal settings
  68. MULTIPLEXAH     equ     72h             ; Multiplex int 2F AH parameter
  69. V_FORMAT        equ     0               ; config_s format version used here
  70.  
  71. HOOKINT19       equ     FALSE           ; Hook int 19 if TRUE
  72.  
  73. DEBUGGING       equ     FALSE
  74. DEBUGINIT       equ     FALSE
  75.  
  76. ; Derived definitions
  77.  
  78. DR_ATTRIBUTES = 0800h                   ; Removable media
  79.  
  80. if CAPABLE and C_32BITSEC
  81. DR_ATTRIBUTES = DR_ATTRIBUTES or 2      ; 32-bit addr
  82. endif
  83.  
  84. if XMS_MEMORY
  85. .286c
  86. MEMSTR  equ 'XMS '      ; Define 4 char memory type string
  87. else
  88.   %out Memory defined by MEMORY not supported
  89.   .err
  90. endif
  91.  
  92. if DEBUGGING
  93. debug   macro char,num
  94.         push ax
  95.         push dx
  96.         mov dx,num
  97.         mov al,char
  98.         call debug_c
  99.         pop dx
  100.         pop ax
  101.         endm
  102. else
  103. debug   macro char
  104.         endm
  105. endif ;DEBUGGING
  106.  
  107. d_seg           segment para public
  108.                 assume ds:d_seg, cs:d_seg
  109.  
  110.                 org     0
  111. ; The following is to be considered as both a device driver header and
  112. ; as a starting point for the configuration table. This driver will be
  113. ; identified by its segment address and this structure must be at offset
  114. ; 0.
  115.  
  116.                 ; Device driver header
  117. drhdr_next      dd      -1              ; Pointer to next device (now last)
  118. drhdr_attr      dw      DR_ATTRIBUTES
  119. drhdr_strategy  dw      offset strategy ; Offset to strategy function
  120. drhdr_commands  dw      offset commands ; Offset to commands function
  121. drhdr_units     db      1               ; Number of units
  122.  
  123. ; The rest has four functions to be considered
  124. ;  1) usable as device driver name if this driver is changed
  125. ;     into character device on init.
  126. ;  2) usable as a label to be returned in media check call
  127. ;  3) identifies this device driver as SRDISK driver by always having
  128. ;     the letters SRD at offset dr_ID
  129. ;  4) identifies the memory used by the 4 char string at offset dr_memory
  130.  
  131. dr_volume       label byte
  132. dr_ID           db      'SRD'           ; SRDISK identification (3 char)
  133. dr_memory       db      MEMSTR          ; Memory type identifier (4 char)
  134. dr_version      db      SRD_VERSION     ; Device driver version (4 char)
  135.                 db      0               ; null to end volume label
  136. dr_v_format     db      V_FORMAT        ; Configuration format version
  137. dr_conf         dw      offset conf     ; Pointer to drive configuration
  138.  
  139.  
  140. ;**************************************************************************
  141. ;
  142. ;               I/O ROUTINE TO THE RAM DISK
  143. ;
  144. ; This routine will read a group of sectors inside this part of
  145. ; the ram disk. If starting sector is not on this part of the disk,
  146. ; return without error with 0 sectors transferred. If not all sectors
  147. ; are on this part of the disk, transfer as many as can and report the
  148. ; number of sectors transferred.
  149. ;
  150. ; On entry
  151. ;   bh - 0 then read, else write
  152. ;   cx - number of sectors
  153. ;   dx:ax - starting sector
  154. ;   es:di - transfer buffer
  155. ;
  156. ; Preserve
  157. ;   es, ds
  158. ;   si, di
  159. ;
  160. ; Return
  161. ;   - carry clear if no fatal error, transferred sector count in ax
  162. ;       (if starting sector not in this part of disk, return ax = 0)
  163. ;   - carry set and ax = 0 on fatal error
  164. ;
  165. ;**************************************************************************
  166.  
  167. if XMS_MEMORY
  168. disk_IO         proc far
  169.                 push ds
  170.                 push di
  171.                 push si
  172.  
  173.                 push cs                         ; Make ds point to our data
  174.                 pop ds
  175.  
  176.                 mov IO_startl,ax
  177.                 mov IO_starth,dx
  178.                 debug 'a',ax
  179.                 debug 'd',dx
  180.                 debug 'c',cx
  181.  
  182.                 cmp     ax,conf.c_sectorsl      ; Starting sector on disk?
  183.                 sbb     dx,conf.c_sectorsh
  184.                 jb disk_IO4                     ; Yes
  185.  
  186.                 debug 'O',ax
  187.                 xor ax,ax                       ; No, 0 sectors transferred
  188.                 clc                             ;  No fatal error
  189.                 jmp disk_IOx                    ;  Exit
  190.  
  191. disk_IO4:       mov dx,IO_starth
  192.                 add     ax,cx                   ; Count ending sector
  193.                 adc     dx,0
  194.                 cmp dx,conf.c_sectorsh          ; Ending sector on disk?
  195.                 jb disk_IO1                     ; Jump if is
  196.                 jne disk_IO5
  197.                 sub     ax,conf.c_sectorsl
  198.                 jbe     disk_IO1                ; Jump if is
  199. disk_IO5:
  200.                 sub cx,ax                       ; Count how many we CAN transfer
  201.                 debug 'T',cx
  202. disk_IO1:
  203.                 mov IO_sectors,cx               ; Report # of transferred
  204.                 mov     ax,cx                   ; Count number of bytes to move
  205.                 mul     conf.c_BPB_bps
  206.                 mov     si,offset XMS_cblk
  207.                 mov     [si].XMS_sizel,ax       ; Number of bytes to move
  208.                 mov     [si].XMS_sizeh,dx
  209.  
  210.                 mov ax,IO_starth                ; Count starting byte
  211.                 mul conf.c_BPB_bps
  212.                 mov cx,ax
  213.                 mov ax,IO_startl
  214.                 mul conf.c_BPB_bps
  215.                 add dx,cx                       ; dx:ax is starting byte
  216.   
  217.                 or      bh,bh                   ; Input/output?
  218.                 mov     bx,XMS_handle
  219.                 jnz     disk_IO2                ; Jump if write
  220.                                                 ; -- Read
  221.                 mov     [si].XMS_shandle,bx     ; Source in XMS
  222.                 mov     [si].XMS_soffl,ax
  223.                 mov     [si].XMS_soffh,dx
  224.                 mov     [si].XMS_dhandle,0      ; Destination in main memory
  225.                 mov     [si].XMS_doffl,di
  226.                 mov     [si].XMS_doffh,es
  227.                 jmp     disk_IO3
  228. disk_IO2:                                       ; -- Write
  229.                 mov     [si].XMS_shandle,0      ; Destination in main memory
  230.                 mov     [si].XMS_soffl,di
  231.                 mov     [si].XMS_soffh,es
  232.                 mov     [si].XMS_dhandle,bx     ; Source in XMS
  233.                 mov     [si].XMS_doffl,ax
  234.                 mov     [si].XMS_doffh,dx
  235. disk_IO3:
  236.                 mov     ah,0Bh                  ; Move XMS block
  237.                 call    dword ptr XMS_entry
  238.                 shr     ax,1
  239.                 cmc                             ; Carry set if err
  240.                 mov     ax,IO_sectors           ; Return # of sectors xferred
  241.                 jnc disk_IOx
  242.                   xor ax,ax
  243. disk_IOx:       pop si                          ; Restore original si,di,ds
  244.                 pop di                          ;  es was not changed
  245.                 pop ds
  246. ret_far:        ret
  247. disk_IO         endp
  248.  
  249.   
  250. ;**************************************************************************
  251. ;
  252. ;               EXTERNAL MEMORY ALLOCATION ROUTINE
  253. ;
  254. ; Allocate requested amount of memory. If memory is available in chunks,
  255. ; the amount can be rounded up. If not enough memory available, allocate
  256. ; as much as possible or just report the amount that was previously
  257. ; allocated. It is expected that at least as much memory can be allocated
  258. ; as there previously was. Reallocation should not destroy memory
  259. ; contents - it is essential to be able to resize a disk without loosing
  260. ; the contents (a feature under development).
  261. ;
  262. ; On entry
  263. ;   DWORD [sp+4] - Kbytes to allocate
  264. ;
  265. ; Preserve
  266. ;   es, ds
  267. ;   si, di
  268. ;
  269. ; Return dx:ax = Kbytes allocated
  270. ;
  271. ;**************************************************************************
  272.  
  273. malloc          proc C far
  274.                 arg kbytes:dword
  275.                 assume ds:nothing
  276.                 test word ptr kbytes+2,-1       ; Over 0FFFFh K is impossible
  277.                 jnz malloc_fail
  278.                 mov bx,word ptr kbytes          ; New disk size
  279.                 mov dx,word ptr XMS_handle      ; Handle to the memory
  280.                 mov ah,0Fh                      ; Reallocate
  281.                 call XMS_entry
  282.                 xor dx,dx                       ; Zero the high word of return
  283.                 or ax,ax
  284.                 jnz malloc_ok
  285.  
  286. malloc_fail:    mov ax,word ptr conf.c_size     ; Fail, return current
  287.                 ret
  288.  
  289. malloc_ok:      mov ax,word ptr kbytes          ; Ok, return requested
  290.                 ret
  291.  
  292.                 assume ds:d_seg
  293. malloc          endp
  294.  
  295.  
  296. ;**************************************************************************
  297. ;
  298. ;                       Warm Boot of Machine
  299. ;
  300. ; Release used XMS memory on warm boot.
  301. ;
  302. ; I guess this may be important if some virtual machine (VM) in some
  303. ; multitasking system has installed this driver and the VM is ended.
  304. ; Without this the other VMs would loose the space reserved for RAM disk
  305. ; in this VM.
  306. ;**************************************************************************
  307.   
  308. if HOOKINT19
  309.  
  310. int_19_entry    proc far
  311.                 assume ds:nothing
  312.                 pusha   ; If XMS used, it must be 286 or above
  313.                 mov     dx,XMS_handle
  314.                 cmp     dx,-1
  315.                 je      int19_1                 ; Jump if no XMS handle
  316.         mov    ah,0Ah
  317.                 call    XMS_entry               ; Free XMS memory
  318. int19_1:
  319.                 xor     ax,ax
  320.         mov    ds,ax
  321.                 mov     ax,old_int19_off
  322.         cli                ; Disable interrupts
  323.                 mov     ds:[19h*4],ax           ; for the time to write
  324.                 mov     ax,old_int19_seg        ; old interrupt vector back
  325.                 mov     ds:[19h*4+2],ax
  326.                 popa                            ; Enable interrupts
  327.                 jmp     old_int19
  328.                 assume ds:d_seg
  329. int_19_entry    endp
  330.  
  331. endif
  332.  
  333. ;**************************************************************************
  334. ;
  335. ;                       Local data
  336. ;
  337. ; This data (as some from the Configuration tables too) is used by the
  338. ; two above routines that are needed resident in any case.
  339. ;
  340. ;**************************************************************************
  341.  
  342. XMS_block       struc
  343. XMS_sizel       dw ?
  344. XMS_sizeh       dw ?
  345. XMS_shandle     dw ?
  346. XMS_soffl       dw ?
  347. XMS_soffh       dw ?
  348. XMS_dhandle     dw ?
  349. XMS_doffl       dw ?
  350. XMS_doffh       dw ?
  351. XMS_block       ends
  352.  
  353. XMS_cblk        XMS_block <>            ; XMS move command data structure
  354. XMS_entry       dd      ?               ; XMS driver entry point
  355. XMS_handle      dw      -1              ; XMS handle to disk memory
  356.  
  357. IO_sectors      dw      ?               ; Temp storage for # of sec xferred
  358. IO_startl       dw      ?               ; Temp storage for starting sector
  359. IO_starth       dw      ?               ; Temp storage for starting sector
  360.  
  361. else ; if XMS_MEMORY
  362.   %out Memory defined by MEMORY not supported
  363.   .err
  364. endif
  365.  
  366. if HOOKINT19
  367. old_int19       label dword             ; Address of old INT 19
  368. old_int19_off   dw      -1
  369. old_int19_seg   dw      -1
  370. endif
  371.  
  372. ;**************************************************************************
  373. ;
  374. ;                       Debugging code
  375. ;
  376. ; This code prints out a character and a word in hex. This code can be
  377. ; used using "debug char,word" macro in the code to give some output of
  378. ; the actions device driver is doing.
  379. ;
  380. ; A color display is assumed with 80 characters on a row and 25 rows.
  381. ;
  382. ;**************************************************************************
  383.  
  384. if DEBUGGING
  385.                 assume ds:nothing
  386.  
  387. debug_c         proc near
  388.                 push es
  389.                 push di
  390.  
  391.                 mov ah,d_attr           ; Load color attribute
  392.                 mov di,0B800h           ; Load screen segment (assumes color)
  393.                 mov es,di
  394.                 mov di,d_loc            ; Load line
  395.                 cmp di,26*160           ; Below screen?
  396.                 jb debug_c1
  397.                   mov di,2*160          ; Yes, move to third line (for scroll off)
  398.                   mov d_loc,di
  399.                   add ah,10h            ; Change color
  400.                   cmp ah,70h
  401.                   jb debug_c2
  402.                     sub ah,60h
  403. debug_c2:         mov d_attr,ah
  404. debug_c1:
  405.                 add di,d_col            ; Advance to right column
  406.                 mov es:[di],ax          ; Print error letter
  407.  
  408.                 call debug_x            ; Print high byte
  409.                 mov dh,dl
  410.                 call debug_x            ; Print low byte
  411.  
  412.                 add d_loc,160           ; Next line
  413.  
  414.                 pop di
  415.                 pop es
  416.                 ret
  417. debug_c         endp
  418.  
  419. debug_x         proc near               ; Print a byte in hex
  420.                 mov al,dh
  421.                 shr al,1
  422.                 shr al,1
  423.                 shr al,1
  424.                 shr al,1
  425.                 call debug_x1
  426.                 mov al,dh
  427. debug_x1:       and al,0Fh              ; Print a hex digit
  428.                 cmp al,10
  429.                 jae debug_x2
  430.                   add al,'0'
  431.                   jmp debug_x3
  432. debug_x2:       add al,'A'-10
  433. debug_x3:
  434.                 inc di
  435.                 inc di
  436.                 mov es:[di],ax
  437.                 ret
  438. debug_x         endp
  439.  
  440. d_loc   dw 2*160
  441. d_col   dw 150
  442. d_attr  db 40h
  443.  
  444.                 assume ds:d_seg
  445.  
  446. endif ; DEBUGGING
  447.  
  448.  
  449. ;**************************************************************************
  450. ;
  451. ;                       Configuration tables
  452. ;
  453. ; This structure holds all the formatting data used by the formatter.
  454. ; The formatter is passed a pointer to this data and it modifies it
  455. ; directly. For this arrangement to work THE BELOW TABLE MAY NOT BE
  456. ; MODIFIED WITHOUT PROPER CHANGES IN SRDISK.C. The table contains
  457. ; version number which is to be changed when a change is made to this
  458. ; structure.
  459. ;
  460. ; Only the first fields up to label addition_eor is resident and used in
  461. ; in every case. The rest is used only in the main driver in a chain of
  462. ; RAM disk drivers.
  463. ;
  464. ; !!! The formatter will use any initial values in this structure as
  465. ; default values i.e. set all needed values here !!!
  466. ;**************************************************************************
  467.  
  468. READ_ACCESS     equ     1       ; Bit masks for the RW_access
  469. WRITE_ACCESS    equ     2
  470.  
  471. config_s struc
  472. c_drive         db      ?               ; Drive letter
  473. c_flags         db      CAPABLE         ; Misc capability flags
  474. c_disk_IO       dd      disk_IO         ; disk_IO entry
  475. c_malloc        dw      malloc          ; malloc entry offset (in DS/CS)
  476. c_next          dw      0               ; Segment of next driver in chain
  477. c_maxK          dd      0FFFFh          ; Maximum allowed size
  478. c_size          dd      0               ; Current allocated size in Kbytes
  479. c_sectorsl      dw      0               ; Sectors in this driver (low word)
  480. c_sectorsh      dw      0               ; Sectors in this driver (high word)
  481.  
  482. c_BPB_bps       dw      128             ; Sector size
  483. c_BPB_spc       db      4               ; Cluster size 4*128 = 512
  484. c_BPB_reserved  dw      1               ; The boot sector is reserved
  485. c_BPB_FATs      db      1               ; One FAT copy
  486. c_BPB_dir       dw      64              ; 64 entries in root directory
  487. c_BPB_sectors   dw      0               ; BPB number of sectors on disk
  488. c_BPB_media     db      0FAh            ; Media is RAM DISK
  489. c_BPB_FATsectors dw     ?               ; Sectors per one FAT
  490. c_BPB_spt       dw      -1              ; Sectors per track (imaginary)
  491. c_BPB_heads     dw      1               ; Number of heads (imaginary)
  492. c_BPB_hiddenl   dw      0               ; # of hidden sectors (low word) (imag)
  493. c_BPB_hiddenh   dw      0               ; # of hidden sectors (high word)
  494. c_BPB_tsectorsl dw      0               ; 32-bit # of sectors (low word)
  495. c_BPB_tsectorsh dw      0               ; 32-bit # of sectors (high word)
  496.  
  497. c_tsize         dd      0               ; Total size in Kbytes (all drivers)
  498.  
  499. c_RW_access     db      00b             ; B0 = read, B1 = write (disabled now)
  500. c_media_change  db      1               ; -1 if media changed, 1 if not
  501. c_open_files    dw      0               ; Files currently open on drive
  502. c_next_drive    dw      0               ; Segment of next SRDISK drive
  503. config_s ends
  504.  
  505. conf            config_s <>
  506.  
  507. appended_eor    equ conf.c_BPB_spc      ; End of resident for appended driver
  508.  
  509.  
  510. ;**************************************************************************
  511. ;
  512. ;               Other internal and resident data
  513. ;
  514. ; The order of this data is not significant as it will not be used outside
  515. ;
  516. ;**************************************************************************
  517.  
  518. BPB             equ     byte ptr conf.c_BPB_bps
  519. pBPB            dw      offset BPB      ; Pointer to BPB (for cmd_init)
  520.  
  521. old_multiplex   dd      ?               ; Multiplex hook
  522.  
  523. if CAPABLE and C_APPENDED
  524. xaddr_off       dw      ?               ; Temp data for cmd_io
  525. xaddr_seg       dw      ?
  526. xsecl           dw      ?
  527. xsech           dw      ?
  528. endif
  529.  
  530. req_ptr         dd      ?               ; Request structure pointer
  531.  
  532.                 ; Pointers to commands
  533. command_tbl     dw      cmd_init             ;  0 Init
  534.                 dw      cmd_media            ;  1 Media
  535.                 dw      cmd_BPB              ;  2 Build BPB
  536.                 dw      cmd_unknown          ;  3 IOCTL input
  537.                 dw      cmd_input            ;  4 Input
  538.                 dw      cmd_unknown          ;  5 nondest input (char)
  539.                 dw      cmd_unknown          ;  6 input status (char)
  540.                 dw      cmd_unknown          ;  7 input flush (char)
  541.                 dw      cmd_output           ;  8 Output
  542.                 dw      cmd_output           ;  9 Output with verify
  543.                 dw      cmd_unknown          ; 10 output status (char)
  544.                 dw      cmd_unknown          ; 11 output flush (char)
  545.                 dw      cmd_unknown          ; 12 IOCTL output
  546.                 dw      cmd_open             ; 13 Open device
  547.                 dw      cmd_close            ; 14 Close device
  548.                 dw      cmd_removable        ; 15 Removable media check
  549.  
  550. HIGH_CMD        EQU ($-offset command_tbl)/2
  551.   
  552. ;**************************************************************************
  553. ;
  554. ;                       Set request header address
  555. ;
  556. ; Called by DOS to set the request structure pointer
  557. ;
  558. ;**************************************************************************
  559.   
  560. strategy        proc far
  561.                 mov     word ptr cs:req_ptr,bx
  562.                 mov     word ptr cs:req_ptr+2,es
  563.                 ret
  564. strategy    endp
  565.   
  566.   
  567. ;**************************************************************************
  568. ;
  569. ;                       Commands
  570. ;
  571. ; Called by DOS. Requested action defined in structure pointed by req_ptr.
  572. ;
  573. ;**************************************************************************
  574.   
  575. commands        proc far
  576.                 assume ds:nothing
  577.         push    ax
  578.                 push    bx
  579.         push    cx
  580.         push    dx
  581.                 push    si
  582.         push    di
  583.         push    ds
  584.         push    es
  585.                 cld
  586.                 lds     si,cs:req_ptr
  587.                 ; We trust Microsoft that the unit is right at [req_ptr]+1
  588.                 mov     cx,[si+12h]             ; Sectors/Cmd line/BPB pointer
  589.                 mov     dx,[si+14h]             ; Start sector/Device number
  590.                 mov     bl,[si+2]               ; Command
  591.                 cmp     bl,HIGH_CMD             ; Is command supported?
  592.                 ja      cmd_unknown             ; Jump if not
  593.                 xor     bh,bh                   ; Count index to command_tbl
  594.                 shl     bx,1
  595.                 les     di,dword ptr [si+0Eh]   ; ES:DI = transfer address
  596.         push    cs
  597.                 pop     ds                      ; DS to local data segment
  598.                 assume ds:d_seg
  599.                 jmp     word ptr [command_tbl+bx] ; Do command
  600. cmd_unknown:
  601.                 assume ds:nothing
  602.                 mov     al,3
  603.                 jmp     cmd_error
  604. cmd_IOerr:
  605.                 lds     bx,req_ptr
  606.                 mov     word ptr [bx+12h],0     ; Sector count zero
  607. cmd_error:
  608.                 mov     ah,81h                  ; ERROR and DONE
  609.                 jmp     cmd_ret
  610.  
  611. cmd_removable:  ; Enough to return DONE without BUSY flag set
  612. cmd_ok:
  613.                 mov     ah,1                    ; DONE
  614. cmd_ret:
  615.                 lds     bx,req_ptr
  616.                 mov     [bx+3],ax               ; save status
  617.         pop    es
  618.         pop    ds
  619.         pop    di
  620.                 pop     si
  621.         pop    dx
  622.         pop    cx
  623.                 pop     bx
  624.         pop    ax
  625.         retf                ; Return far
  626.                 assume ds:d_seg
  627. commands    endp
  628.  
  629. ;**************************************************************************
  630. ;
  631. ;               Media Check command
  632. ;
  633. ;**************************************************************************
  634.  
  635. cmd_media       proc near
  636.                 les     bx,req_ptr
  637.  
  638.                 mov     ax,100h                 ; DONE status
  639.                 mov     dh,conf.c_media_change  ; Read the change return
  640.  
  641.                 test    conf.c_RW_access,READ_ACCESS
  642.                 jnz     cmd_media1
  643.                 mov     ax,8102h                ; "Device not ready" status
  644.                 mov     dh,-1                   ; "Changed"
  645. cmd_media1:
  646.                 mov     es:[bx+0Eh],dh
  647.                 mov     word ptr es:[bx+0Fh],offset dr_volume
  648.                 mov     es:[bx+11h],cs
  649.                 jmp     cmd_ret
  650. cmd_media       endp
  651.  
  652.  
  653. ;**************************************************************************
  654. ;
  655. ;               Build BPB command
  656. ;
  657. ;**************************************************************************
  658.  
  659. cmd_BPB         proc near
  660.                 les     bx,req_ptr
  661.                 mov     word ptr es:[bx+12h],offset BPB
  662.                 mov     es:[bx+14h],cs
  663.                 mov     conf.c_open_files,0  ; Reset open files to 0
  664.                 mov     conf.c_media_change,1 ; Media not changed
  665.                 test    conf.c_RW_access,READ_ACCESS
  666.                 jz      cmd_BPB1
  667.                 jmp     cmd_ok
  668. cmd_BPB1:
  669.                 mov     al,2                    ; "Device not ready"
  670.                 jmp     cmd_error
  671. cmd_BPB         endp
  672.  
  673.  
  674. ;**************************************************************************
  675. ;
  676. ;               Device Open command
  677. ;
  678. ;**************************************************************************
  679.  
  680. cmd_open        proc near
  681.                 inc     conf.c_open_files
  682.                 jmp     cmd_ok
  683. cmd_open        endp
  684.  
  685.  
  686. ;**************************************************************************
  687. ;
  688. ;               Device Close command
  689. ;
  690. ;**************************************************************************
  691.  
  692. cmd_close       proc near
  693.                 cmp     conf.c_open_files,0
  694.                 jz      cmd_close1
  695.                 dec     conf.c_open_files
  696. cmd_close1:
  697.                 jmp     cmd_ok
  698. cmd_close       endp
  699.  
  700.  
  701. ;**************************************************************************
  702. ;
  703. ;               INPUT command
  704. ;
  705. ;**************************************************************************
  706.  
  707. cmd_input       proc near
  708.                 test    conf.c_RW_access,READ_ACCESS
  709.                 jz      cmd_input1
  710.                 xor     bh,bh
  711.                 jmp     cmd_io
  712. cmd_input1:
  713.                 mov     al,2                    ; "Device not ready"
  714.                 jmp     cmd_IOerr
  715. cmd_input       endp
  716.  
  717.  
  718. ;**************************************************************************
  719. ;
  720. ;               OUTPUT command
  721. ;
  722. ;**************************************************************************
  723.  
  724. cmd_output      proc near
  725.                 mov     al,0                    ; "Write protect violation"
  726.                 mov     bh,1
  727.                 test    conf.c_RW_access,WRITE_ACCESS
  728.                 jnz cmd_io
  729.                   jmp cmd_output2
  730. cmd_io:
  731.                 ; BH    - read/write
  732.                 ; CX    - sectors
  733.                 ; ES:DI - transfer address
  734.                 ; DS    = CS
  735.  
  736.                 mov ax,cx                       ; Count number of bytes to move
  737.                 mul conf.c_BPB_bps
  738.                 jc cmd_output4                  ; Is it too much? (dx != 0)
  739.  
  740.                 ; check transfer address and count that they do not
  741.                 ; exceed segment limit
  742.                 add ax,di                       ; (dx = 0 after the mul)
  743.                 jnc cmd_output5
  744. cmd_output4:
  745.                 mov ax,di                       ; How many bytes CAN we move?
  746.                 xor ax,-1
  747.                 xor dx,dx                       ; How many sectors?
  748.                 div conf.c_BPB_bps
  749.                 mov cx,ax
  750. cmd_output5:
  751.                 push es
  752.                 les si,req_ptr
  753.                 mov word ptr es:[si+12h],dx     ; Xferred 0 sectors so far
  754.                 cmp byte ptr es:[si],1Ah        ; Do we use 32-bit sec. address?
  755.                 jbe cmd_output3
  756.                   debug '3',0
  757.                   mov ax,es:[si+1Ah]            ; Load 32-bit sec. address
  758.                   mov dx,es:[si+1Ch]
  759.                   jmp cmd_output8
  760. cmd_output3:
  761.                 mov ax,es:[si+14h]              ; Load 16-bit sec. address
  762.                 xor dx,dx
  763. cmd_output8:
  764.                 pop es
  765.  
  766. if CAPABLE and C_APPENDED
  767.  
  768.                 mov si,offset conf
  769.                 mov xaddr_off,di
  770.                 mov xaddr_seg,es
  771.                 mov xsecl,ax
  772.                 mov xsech,dx
  773.                 ; BH    - read/write
  774.                 ; CX    - sectors
  775.                 ; DS:SI - conf of current driver (main here)
  776.  
  777. cmd_output7:
  778.                 push bx
  779.                 push cx
  780.                 call [si].c_disk_IO
  781.                 pop cx
  782.                 pop bx
  783.  
  784.                 les di,cs:req_ptr               ; Increment number of sectors
  785.                 add word ptr es:[di+12h],ax     ;  actually transferred
  786.  
  787.                 jc cmd_output1                  ; I/O error
  788.  
  789.                 sub cx,ax                       ; All transferred?
  790.                 jbe cmd_output6                 ;  yes, so exit
  791.  
  792.                 debug 'N',ax
  793.                 push ax
  794.                 mul [si].c_BPB_bps              ; Increment transfer offset
  795.                 add cs:xaddr_off,ax             ;  which can not exceed 0FFFFh
  796.                 pop ax
  797.  
  798.                 xor dx,dx
  799.                 add ax,cs:xsecl                 ; Count new starting sector
  800.                 adc dx,cs:xsech
  801.                 sub ax,conf.c_sectorsl          ; Subtract passed sectors
  802.                 sbb dx,conf.c_sectorsh
  803.                 mov cs:xsecl,ax                 ; And store the result
  804.                 mov cs:xsech,dx
  805.  
  806.                 mov es,cs:xaddr_seg             ; Load these ready for disk_IO
  807.                 mov di,cs:xaddr_off
  808.                 mov ds,[si].c_next              ; Find next driver
  809.                 mov si,dr_conf
  810.                 or si,si
  811.                 jnz cmd_output7
  812.                 ; there is no next driver - sectors not found!
  813.                 debug 'E',cx
  814.  
  815. else ;if CAPABLE and C_APPENDED
  816.  
  817.                 push cx
  818.                 call disk_IO
  819.                 pop cx
  820.                 les si,cs:req_ptr               ; Return number of sectors
  821.                 mov word ptr es:[si+12h],ax     ;  actually transferred
  822.                 jc cmd_output1                  ; I/O error
  823.                 cmp ax,cx
  824.                 je cmd_output6
  825. endif
  826.  
  827. cmd_output1:
  828.                 debug 'S',ax
  829.                 mov     al,8                    ; "Sector not found"
  830. cmd_output2:
  831.                 jmp     cmd_IOerr
  832. cmd_output6:
  833.                 jmp     cmd_ok
  834. cmd_output      endp
  835.   
  836.  
  837. ;**************************************************************************
  838. ;
  839. ;               MULTIPLEX server
  840. ;
  841. ;**************************************************************************
  842.  
  843. multiplex       proc far
  844.                 cmp ax,MULTIPLEXAH * 100h
  845.                 jne mplex_old
  846.                 mov al,-1               ; Tell we are installed
  847.                 push cs                 ; Tell our segment
  848.                 pop es
  849.                 iret
  850. mplex_old:
  851.                 jmp cs:old_multiplex
  852. multiplex       endp
  853.  
  854.  
  855. ;**************************************************************************
  856. ;**************************************************************************
  857. ;**************************************************************************
  858. ;**************************************************************************
  859. ;
  860. ;               INITIALIZATION TIME CODE
  861. ;
  862. ; This code and data is removed from the memory after driver is
  863. ; initialized.
  864. ;**************************************************************************
  865.  
  866. end_of_resident label byte      ; MARKS THE END OF RESIDENT PORTION OF DRIVER
  867.  
  868. def_drive       db 'C'                  ; Default drive, where to install
  869.  
  870. main_config     dd      ?               ; Pointer to main configuration table
  871.  
  872. FLAG_1ST        EQU 1                   ; First SRDISK driver
  873. FLAG_FORCEDRIVE EQU 2                   ; Force drive letter (in s_drive)
  874. FLAG_APPEND     EQU 4                   ; Append to other SRDISK driver
  875. FLAG_APPENDED   EQU 8                   ; Appended to other SRDISK driver
  876. flags           db 0
  877.  
  878. ;**************************************************************************
  879. ;
  880. ;                       prints macro
  881. ;
  882. ; This macro is used by initialization routines to display text.
  883. ; dx must point to the '$' terminated text about to be displayed.
  884. ;**************************************************************************
  885.   
  886. prints        macro
  887.         mov    ah,9
  888.                 int     21h
  889.               endm
  890.   
  891. if DEBUGINIT
  892. print_x         proc near               ; Print a dword in hex
  893. print_lx:       push ax
  894.                 mov ax,dx
  895.                 call print_sx
  896.                 mov ah,2
  897.                 mov dl,':'
  898.                 int 21h
  899.                 pop ax
  900. print_sx:                               ; Print a word in hex
  901.                 push ax
  902.                 mov al,ah
  903.                 call print_cx
  904.                 pop ax
  905. print_cx:                               ; Print a byte in hex
  906.                 push ax
  907.                 shr al,1
  908.                 shr al,1
  909.                 shr al,1
  910.                 shr al,1
  911.                 call print_x1
  912.                 pop ax
  913. print_x1:       and al,0Fh              ; Print a hex digit
  914.                 cmp al,10
  915.                 jae print_x2
  916.                   add al,'0'
  917.                   jmp print_x3
  918. print_x2:       add al,'A'-10
  919. print_x3:       mov ah,2
  920.                 push dx
  921.                 mov dl,al
  922.                 int 21h
  923.                 pop dx
  924.                 ret
  925. print_x         endp
  926.  
  927. idebugc  macro chr
  928.         push ax
  929.         mov al,chr
  930.         call print_cx
  931.         pop ax
  932. endm
  933.  
  934. idebugs  macro wrd
  935.         push ax
  936.         mov ax,wrd
  937.         call print_sx
  938.         pop ax
  939. endm
  940.  
  941. idebugl  macro high,low
  942.         push ax
  943.         push dx
  944.         mov ax,low
  945.         mov dx,high
  946.         call print_lx
  947.         mov ah,2
  948.         mov dl,' '
  949.         int 21h
  950.         pop ax
  951.         pop dx
  952. endm
  953.  
  954. else
  955.  
  956. idebugc  macro chr
  957. endm
  958.  
  959. idebugs  macro wrd
  960. endm
  961.  
  962. idebugl  macro high,low
  963. endm
  964.  
  965. endif
  966.  
  967.   
  968. ;**************************************************************************
  969. ;
  970. ;                       INIT command
  971. ;
  972. ; Init command does the following:
  973. ;  - displays sign-on message
  974. ;  - checks DOS version. This driver is built in a way that requires
  975. ;    at least dos version 2.00. I'm not sure whether even that is enough.
  976. ;  - determine which drive we are by default
  977. ;  - read command line
  978. ;    - abort on syntax errors
  979. ;  - initialize memory to 0K disk
  980. ;  - initialize multiplex interrupt
  981. ;  - do hooks to other SRDISK drivers (specified in command line)
  982. ;  - hook INT 19 bootstrap interrupt
  983. ;  - fills in the request header
  984. ;**************************************************************************
  985.   
  986. cmd_init        proc near
  987.                 mov     dx,offset s_sign_on     ; "ReSizeable RAMdisk ver..."
  988.                 prints
  989.  
  990.                 mov     ah,30h
  991.                 int     21h                     ; Get DOS version number
  992.  
  993.         xchg    ah,al
  994.                 idebugs ax
  995.                 cmp     ax,200h
  996.                 jb      cmd_init1
  997.         cmp    ax,600h
  998.                 jb      cmd_init2
  999. cmd_init1:
  1000.                 mov     dx,offset errs_eDOS
  1001.                 jmp     cmd_init_err
  1002. cmd_init2:
  1003.                 cmp ax,400h
  1004.                 jae cmd_init4
  1005.  
  1006.                 and conf.c_flags,NOT C_32BITSEC
  1007. cmd_init4:
  1008.                 les     si,req_ptr
  1009.                 idebugl es,si
  1010.                 idebugc <byte ptr es:[si]>
  1011.                 idebugc <byte ptr es:[si+2]>
  1012.                 idebugs <word ptr es:[si+16h]>
  1013.                 cmp     byte ptr es:[si],16h    ; Device number supported?
  1014.                 mov al,'$'                      ; Unknown drive
  1015.                 jbe     cmd_init8               ; No, make a guess
  1016.  
  1017.                 mov     al,es:[si+16h]          ; Get drive number
  1018.                 add al,'A'
  1019. cmd_init8:
  1020.                 mov s_drive,al
  1021.                 mov def_drive,al
  1022.                 jmp cmd_init5
  1023.  
  1024. cmd_init5:      call init_read_cmdline
  1025.                 jc cmd_init_err
  1026.  
  1027.                 call    init_memory
  1028.                 jc      cmd_init_err
  1029.  
  1030.                 call init_mplex
  1031.                 jc cmd_init_err
  1032.  
  1033.                 call init_hooks
  1034.                 jc cmd_init_err
  1035.  
  1036. if HOOKINT19
  1037.                 call    set_int19
  1038. endif
  1039.                 mov     word ptr conf.c_disk_IO+2,cs
  1040.  
  1041.                 mov al,s_drive
  1042.                 mov conf.c_drive,al
  1043.  
  1044.                 test flags,FLAG_APPENDED
  1045.                 jz cmd_init7
  1046.                   mov s_appdrive,al     ; Report append
  1047.                   mov dx,offset s_appended
  1048.                   prints
  1049.  
  1050.                   mov bx,offset ret_far ; Strategy and commands short
  1051.                   mov drhdr_strategy,bx
  1052.                   mov drhdr_commands,bx
  1053.                   mov drhdr_attr,8000h  ; Plain character device
  1054.                   mov drhdr_units,'$'   ; Name for this driver '$RDISK'
  1055.  
  1056.                   lds bx,req_ptr
  1057.                   mov byte ptr [bx+0Dh],1       ; One drive
  1058.                   mov [bx+0Eh],offset appended_eor ; Ending address
  1059.                   jmp cmd_init3
  1060.  
  1061. cmd_init_err:
  1062.                 prints
  1063. cmd_init_abort:
  1064.                 call deinit                     ; Remove hooks
  1065.                 xor     ax,ax
  1066.                 lds bx,req_ptr
  1067.                 mov     byte ptr [bx+0Dh],al    ; Zero the number of drives
  1068.                 mov     [bx+0Eh],ax             ; Ending address
  1069.                 jmp     cmd_init3
  1070.  
  1071. cmd_init7:      ; Not appended to previously installed SRDISK driver
  1072.                 mov al,s_drive
  1073.                 cmp al,'$'                      ; Is the drive number known?
  1074.                 jne cmd_init9
  1075.                   mov word ptr s_drive,2020h    ; Don't tell drive
  1076. cmd_init9:
  1077.                 push ax                         ; Save al for forcing
  1078.                 mov dx,offset s_installed       ; Report install
  1079.                 prints
  1080.                 pop ax
  1081.  
  1082.                 lds     bx,req_ptr
  1083.                 mov     byte ptr [bx+0Dh],1     ; Save number of drives
  1084.  
  1085.                 cmp byte ptr [bx],16h
  1086.                 jbe cmd_init6
  1087. ;                 mov al,s_drive                ; Force drive number
  1088.                   cmp al,'$'                    ; Is the number known?
  1089.                   je cmd_init6
  1090.                   sub al,'A'
  1091.                   mov [bx+16h],al
  1092. cmd_init6:
  1093.                 mov     word ptr [bx+0Eh],offset end_of_resident
  1094. cmd_init3:
  1095.                 mov     [bx+10h],cs
  1096.                 mov     word ptr [bx+12h],offset pBPB
  1097.                 mov     [bx+14h],cs
  1098.                 jmp     cmd_ok
  1099.  
  1100. cmd_init        endp
  1101.   
  1102. ;**************************************************************************
  1103. ;
  1104. ;               READ COMMAND LINE
  1105. ;
  1106. ; Return carry set if error
  1107. ;**************************************************************************
  1108.  
  1109. init_read_cmdline proc near
  1110.                 push ds
  1111.  
  1112.                 les bx,req_ptr
  1113.                 lds si,es:[bx+12h]              ; Pointer to cmd line
  1114.                 assume ds:nothing
  1115.  
  1116. irc1:           lodsb                           ; Skip over the driver name
  1117.                 cmp al,9 ;tab
  1118.                 je irc2
  1119.                 cmp al,' '
  1120.                 je irc2
  1121.                 ja irc1
  1122.                 jmp irc_eol
  1123. irc2:
  1124. irc_narg:       call irc_skip_space
  1125.  
  1126.                 cmp al,' '                      ; Every ctrl character ends
  1127.                 jb irc_eol
  1128.  
  1129.                 cmp al,'/'
  1130.                 jz irc_switch
  1131.  
  1132.                 and al,11011111b                ; Make lowercase to uppercase
  1133.                 cmp al,'A'
  1134.                 jb irc_syntax
  1135.                 cmp al,'Z'
  1136.                 ja irc_syntax
  1137.  
  1138.                 cmp byte ptr [si],':'
  1139.                 jne irc3
  1140.                 inc si                          ; Skip ':'
  1141. irc3:           
  1142.                 mov byte ptr s_drive,al
  1143.                 test flags,FLAG_FORCEDRIVE
  1144.                 jnz irc_syntax
  1145.                 or flags,FLAG_FORCEDRIVE
  1146.                 jmp irc_narg
  1147.  
  1148. irc_syntax:     mov dx,offset errs_syntax
  1149.                 stc
  1150.                 pop ds
  1151.                 ret
  1152.  
  1153. irc_switch:     lodsb
  1154.                 and al,11011111b                ; Make lowercase to uppercase
  1155.                 cmp al,'A'
  1156.                 jne irc_syntax
  1157.  
  1158.                 or flags,FLAG_APPEND
  1159.                 jmp irc_narg
  1160.  
  1161. irc_eol:        clc
  1162.                 pop ds
  1163.                 ret
  1164. init_read_cmdline endp
  1165.  
  1166. irc_skip_space  proc near
  1167. ircs1:          lodsb
  1168.                 cmp al,' '
  1169.                 je ircs1
  1170.                 cmp al,9 ;tab
  1171.                 je ircs1
  1172.                 ret
  1173. irc_skip_space  endp
  1174.  
  1175.                 assume ds:d_seg
  1176.  
  1177.   
  1178. ;**************************************************************************
  1179. ;
  1180. ;                       Memory initialization
  1181. ;
  1182. ; Returns
  1183. ;   carry set if error
  1184. ;**************************************************************************
  1185.   
  1186. if XMS_MEMORY
  1187. ; Get XMS driver API address and allocates 0K to get a memory handle
  1188. ; for RAM disk
  1189.  
  1190. init_memory     proc near
  1191.                 push    es
  1192.                 mov     ax,4300h
  1193.                 int     2Fh                     ; Get XMS installed status
  1194.                 cmp     al,80h
  1195.                 jne     init_XMS1               ; Jump if not installed
  1196.                 mov     ax,4310h
  1197.                 int     2Fh                     ; Get XMS entry point
  1198.                 jnc     init_XMS2               ; Jump if no error
  1199. init_XMS1:
  1200.                 mov     dx,offset errs_noXMS    ; "No extended mem driver"
  1201.                 jmp     init_XMS4
  1202. init_XMS2:
  1203.                 mov     word ptr XMS_entry,bx
  1204.                 mov     word ptr XMS_entry+2,es
  1205.                 xor     dx,dx                   ; Allocate 0K to get a handle
  1206.                 mov     ah,9
  1207.                 call    XMS_entry
  1208.                 or      ax,ax
  1209.                 jz      init_XMS3               ; Zero for failure
  1210.                 mov     XMS_handle,dx
  1211.                 clc
  1212.                 jmp     init_XMS_ret
  1213. init_XMS3:
  1214.                 mov     dx,offset errs_ealloc   ; "Error in ext mem alloc"
  1215. init_XMS4:
  1216.                 stc
  1217. init_XMS_ret:
  1218.                 pop     es
  1219.                 ret
  1220. init_memory     endp
  1221.  
  1222. else
  1223.   %out Memory defined by MEMORY not supported
  1224.   .err
  1225. endif
  1226.  
  1227.  
  1228. ;**************************************************************************
  1229. ;
  1230. ;               Multiplex service initialization
  1231. ;
  1232. ; Queries multiplex interrupt to find out if SRDISK device drivers are
  1233. ; already installed. If not  install the multiplex server.
  1234. ;
  1235. ; Return carry set if error.
  1236. ;**************************************************************************
  1237.  
  1238. init_mplex      proc near
  1239.                 push ds
  1240.                 push es
  1241.                 mov ax,MULTIPLEXAH * 100h
  1242.                 xor bx,bx
  1243.                 xor cx,cx
  1244.                 xor dx,dx
  1245.                 int 2Fh         ; ES segmet of main SRDISK driver
  1246.  
  1247.                 cmp al,-1       ; Is something installed?
  1248.                 je im_installed
  1249.                 cmp al,0        ; Is it OK to install?
  1250.                 je im_install
  1251.  
  1252. im_used:        ; Garbled return
  1253.                 mov dx,offset errs_ml_used
  1254. im_err:         stc
  1255.                 jmp imx
  1256.  
  1257. im_installed:   cmp word ptr es:dr_ID,'RS'      ; Is it SRDISK structure?
  1258.                 jne im_used                     ; No, multiplex used elsewhere
  1259.                 cmp byte ptr es:dr_ID+2,'D'
  1260.                 jne im_used                     ; No, multiplex used elsewhere
  1261.                 mov dx,offset errs_ml_version
  1262.                 cmp byte ptr es:dr_v_format,V_FORMAT ; Proper version?
  1263.                 jne im_err              ; No
  1264.                 ; OK
  1265.                 mov di,es:dr_conf
  1266.                 mov word ptr main_config,di
  1267.                 mov word ptr main_config+2,es
  1268.                 jmp im_end
  1269.  
  1270. im_install:     mov word ptr main_config,offset conf
  1271.                 mov word ptr main_config+2,ds
  1272.                 or flags,FLAG_1ST
  1273.  
  1274.                 mov ax,352Fh
  1275.                 int 21h
  1276.                 mov word ptr old_multiplex,bx
  1277.                 mov word ptr old_multiplex+2,es
  1278.  
  1279.                 mov dx,offset multiplex
  1280.                 mov ax,252Fh
  1281.                 int 21h
  1282.  
  1283. im_end:         clc
  1284. imx:            pop es
  1285.                 pop ds
  1286.                 ret
  1287. init_mplex      endp
  1288.  
  1289.  
  1290. ;**************************************************************************
  1291. ;
  1292. ;               INIT HOOKS to previous SRDISK drivers
  1293. ;
  1294. ; Append this driver into the list of installed SRDISK drivers
  1295. ; Return carry set if error
  1296. ;**************************************************************************
  1297.  
  1298. init_hooks      proc near
  1299.                 test flags,FLAG_1ST     ; If we are the first driver
  1300.                 jnz ihxok               ;  no hooks are to be done
  1301.  
  1302.                 les di,main_config      ; es:di point to a drive config
  1303.                 mov al,s_drive          ; al is the drive to search
  1304.                 cmp al,'$'              ; Is drive letter unknown?
  1305.                 je ih_nodrive           ; Yes, do not check drive letter
  1306.  
  1307.                 test flags,FLAG_APPEND          ; If we append
  1308.                 jz ih_find_drive
  1309.                 test flags,FLAG_FORCEDRIVE      ; but not specify drive
  1310.                 jnz ih_find_drive
  1311. ih_nodrive:       mov al,-1                     ; make sure drive not found
  1312. ih_find_drive:
  1313. ih1:            cmp es:[di].c_drive,al          ; Is it the same drive?
  1314.                 je ih_append
  1315. ih2:            test word ptr es:[di].c_next_drive,-1 ; Is there next drive
  1316.                 jz ih_newdrive                  ; No (valid segment is nonzero)
  1317.                 mov es,es:[di].c_next_drive     ; Yes, find the next drive
  1318.                 mov di,es:dr_conf
  1319.                 jmp ih1
  1320.  
  1321. ih_append_new:  ; Append this driver into previously installed drive
  1322.                 mov al,es:[di].c_drive          ; Find the drive letter
  1323.                 mov s_drive,al
  1324.                 mov conf.c_drive,al
  1325.  
  1326. ih_append:      ; Append this driver into specified drive
  1327.                 test es:[di].c_flags,C_APPENDED ; Append allowed?
  1328.                 jz ih_appendfail                ; No, fail
  1329.  
  1330.                 test word ptr es:[di].c_next,-1 ; Is there next driver
  1331.                 jz ih_a1                        ; No, append here
  1332.                 mov es,es:[di].c_next           ; Yes, find the next drive
  1333.                 mov di,es:dr_conf
  1334.                 jmp ih_append
  1335.  
  1336. ih_appendfail:  mov al,def_drive
  1337.                 mov s_drive,al
  1338.                 mov dx,offset errs_noappend
  1339.                 stc
  1340.                 ret
  1341.  
  1342. ih_a1:          mov es:[di].c_next,ds
  1343.                 or flags,FLAG_APPENDED  ; Remember to free extra memory
  1344. if DEBUGGING
  1345.                 mov ax,es:d_col         ; Debug data little left from
  1346.                 sub ax,16               ;  main data
  1347.                 mov d_col,ax
  1348. endif ;DEBUGGING
  1349.                 jmp ihxok
  1350.  
  1351. ih_newdrive:    test flags,FLAG_APPEND
  1352.                 jnz ih_append_new
  1353.                 ; This driver must be placed at the tail of list of
  1354.                 ; SRDISK drivers
  1355.                 mov es:[di].c_next_drive,ds
  1356.  
  1357. ihxok:          clc
  1358. ihx:
  1359.                 ret
  1360. init_hooks      endp
  1361.  
  1362.  
  1363. ;**************************************************************************
  1364. ;
  1365. ;                       INT 19 hooking
  1366. ;
  1367. ; INT 19 is the bootstrap loader interrupt, which is invoked when user
  1368. ; presses Ctrl-Alt-Del. We must hook it in order to release the
  1369. ; extended memory allocated for RAM disk.
  1370. ;**************************************************************************
  1371.   
  1372. if HOOKINT19
  1373.  
  1374. set_int19       proc near
  1375.         push    ax
  1376.         push    dx
  1377.         push    bx
  1378.         push    es
  1379.  
  1380.                 mov     ax,3519h
  1381.                 int     21h                     ; Get old int 19 handler
  1382.                 mov     old_int19_off,bx
  1383.                 mov     old_int19_seg,es
  1384.                 mov     dx,offset int_19_entry
  1385.         mov    ax,2519h
  1386.                 int     21h                     ; Set new int 19 handler
  1387.  
  1388.         pop    es
  1389.         pop    bx
  1390.         pop    dx
  1391.         pop    ax
  1392.         retn
  1393. set_int19       endp
  1394.   
  1395. endif
  1396.  
  1397. ;**************************************************************************
  1398. ;
  1399. ;               Deinitialization in case of aborted install
  1400. ;
  1401. ;**************************************************************************
  1402.  
  1403. deinit          proc near
  1404. if HOOKINT19
  1405.                 mov ax,old_int19_seg
  1406.                 or ax,old_int19_off
  1407.                 jz di_noint19
  1408.  
  1409.                 push ds
  1410.                 mov dx,old_int19_off
  1411.                 mov ds,old_int19_seg
  1412.                 mov ax,2519h
  1413.                 int 21h                         ; Set old int 19 handler
  1414.                 pop ds
  1415. di_noint19:
  1416. endif
  1417.  
  1418. if XMS_MEMORY
  1419.                 cmp XMS_handle,-1
  1420.                 je di_nomem
  1421.  
  1422.                 mov dx,XMS_handle
  1423.                 mov ah,0Ah
  1424.                 call XMS_entry                  ; Free XMS memory
  1425. else
  1426.   %out Memory defined by MEMORY not supported
  1427.   .err
  1428. endif
  1429.  
  1430. di_nomem:
  1431.                 mov ax,word ptr old_multiplex
  1432.                 or ax,word ptr old_multiplex+2
  1433.                 jz no_mplex
  1434.  
  1435.                 push ds
  1436.                 mov dx,word ptr old_multiplex
  1437.                 mov ds,word ptr old_multiplex+2
  1438.                 mov ax,252Fh
  1439.                 int 21h                         ; Set old multiplex handler
  1440.                 pop ds
  1441. no_mplex:
  1442.  
  1443.                 ret
  1444. deinit          endp
  1445.  
  1446.  
  1447. ;**************************************************************************
  1448. ;
  1449. ;                       Initialization strings
  1450. ;
  1451. ;**************************************************************************
  1452.  
  1453. errs_noXMS      db      'RAMDisk: Extended Memory Manager not present.'
  1454.                 db      0Dh, 0Ah, '$'
  1455.  
  1456. errs_ealloc     db      'RAMDisk: Error in extended memory allocation.'
  1457.                 db      0Dh, 0Ah, '$'
  1458.  
  1459. errs_eDOS       db      'RAMDisk: Incorrect DOS version.'
  1460.                 db      0Dh, 0Ah, '$'
  1461.  
  1462. errs_ml_used    db      'RAMDisk: Multiplex interrupt already in use.'
  1463.                 db      0Dh, 0Ah, '$'
  1464.  
  1465. errs_ml_version db      'RAMDisk: Driver of different version already '
  1466.                 db      'installed.'
  1467.                 db      0Dh, 0Ah, '$'
  1468.  
  1469. errs_noappend   db      'RAMDisk: Can not append to previously installed driver.'
  1470.                 db      0Dh, 0Ah, '$'
  1471.  
  1472. errs_syntax     db      'RAMDisk: Syntax error', 0Dh, 0Ah, 0Dh, 0Ah
  1473.                 db      'Syntax: RDISK.SYS [d:] [/A]', 0Dh, 0Ah, 0Dh, 0Ah
  1474.                 db      ' d:', 9, 'Drive into which to force this driver. '
  1475.                 db      'If another ', 0Dh, 0Ah
  1476.                 db      9, 'SRDISK driver already is installed into '
  1477.                 db      'the same drive', 0Dh, 0Ah
  1478.                 db      9, 'this driver will be appended to the drive.'
  1479.                 db      0Dh, 0Ah
  1480.                 db      ' /A', 9, 'Append this driver to previous SRDISK '
  1481.                 db      'driver.'
  1482.                 db      0Dh, 0Ah, '$'
  1483.  
  1484. s_sign_on       db      0Dh, 0Ah, 'ReSizeable RAMDisk '
  1485. if XMS_MEMORY
  1486.                 db      '(XMS)'
  1487. else
  1488.   %out Memory defined by MEMORY not supported
  1489.   .err
  1490. endif
  1491.                 db      ' version ', SRD_VERSION, '. '
  1492.                 db      'Copyright (c) 1992 Marko Kohtala.'
  1493.                 db      0Dh, 0Ah, '$'
  1494.  
  1495. s_installed     db      'Installed RAMDrive '
  1496. s_drive         db      'C:', 0Dh, 0Ah, '$'
  1497.   
  1498. s_appended      db      'Appended to RAMDrive '
  1499. s_appdrive      db      'C:', 0Dh, 0Ah, '$'
  1500.  
  1501.  
  1502.  
  1503. ;**************************************************************************
  1504. ;
  1505. ;                       A note for binary debuggers
  1506. ;
  1507. ;**************************************************************************
  1508.  
  1509. db "Copyright (c) 1992 Marko Kohtala. "
  1510. db "Contact from Internet, Bitnet etc. to 'Marko.Kohtala@hut.fi', "
  1511. db "CompuServe to '>INTERNET:Marko.Kohtala@hut.fi'"
  1512.  
  1513. d_seg           ends
  1514.                 end
  1515.